package com.zfk.framework.utils;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.File;
import java.net.InetAddress;
import java.io.IOException;

import java.net.ConnectException;
import java.net.Socket;


/**
 * 测试报告生成工具类
 */
public class ReportGenerator {
    private static final Logger logger = LogManager.getLogger(ReportGenerator.class);

    private static final String ALLURE_RESULTS_DIR = "target/allure-results";
    private static final int ALLURE_PORT = 9000;

    /**
     * 启动Allure测试报告服务
     *
     * @return 报告服务的URL，如果启动失败则返回null
     */
    public static String generateAllureReport() {
        try {
            // 清理Allure结果目录
            
            // 检查端口是否已被占用
            if (isPortInUse(ALLURE_PORT)) {
                logger.info("端口 {} 已被占用，正在终止占用进程...", ALLURE_PORT);
                killProcessUsingPort(ALLURE_PORT);
                // 等待一段时间让进程完全终止
                Thread.sleep(1000);
            }
            
            // 启动服务并返回报告URL
            return serveReport();
        } catch (Exception e) {
            logger.error("启动Allure报告服务时发生异常: ", e);
        }
        return null;
    }

    /**
     * 启动报告服务
     *
     * @return 报告服务的URL
     */
    private static String serveReport() {
        try {
            File resultsDir = new File(ALLURE_RESULTS_DIR);

            if (!resultsDir.exists()) {
                logger.warn("Allure结果目录不存在: {}", resultsDir.getAbsolutePath());
                return null;
            }

            // 启动一个新的线程来运行Allure服务
            Thread serveThread = createServeThread();
            serveThread.setDaemon(true); // 设置为守护线程
            serveThread.start();

            // 等待一段时间让服务启动
            Thread.sleep(2000);

            // 获取本机IP地址
            String hostAddress = InetAddress.getLocalHost().getHostAddress();
            String reportUrl = String.format("http://%s:%d", hostAddress, ALLURE_PORT);

            logger.info("Allure报告服务已启动，请访问以下地址查看报告:");
            logger.info("本地访问: http://localhost:{}", ALLURE_PORT);
            logger.info("网络访问: {}", reportUrl);

            return reportUrl;

        } catch (Exception e) {
            logger.warn("启动报告服务时发生异常: ", e);
            return null;
        }
    }

    /**
     * 创建用于运行Allure服务的线程
     *
     * @return Allure服务线程
     */
    private static Thread createServeThread() {
        return new Thread(() -> {
            try {
                ProcessBuilder processBuilder = new ProcessBuilder();
                String os = System.getProperty("os.name").toLowerCase();

                // 使用allure serve命令启动服务，并指定端口和主机
                if (os.contains("win")) {
                    processBuilder.command("cmd", "/c", "allure", "serve", ALLURE_RESULTS_DIR, "--port",
                            String.valueOf(ALLURE_PORT), "--host", "0.0.0.0");
                } else {
                    processBuilder.command("bash", "-c", "allure serve " + ALLURE_RESULTS_DIR + " --port "
                            + ALLURE_PORT + " --host 0.0.0.0");
                }

                Process process = processBuilder.start();
                process.waitFor();
            } catch (Exception e) {
                logger.error("启动Allure服务时发生异常: ", e);
            }
        });
    }
    
    /**
     * 检查指定端口是否正在使用中
     *
     * @param port 要检查的端口号
     * @return 如果端口正在使用中返回true，否则返回false
     */
    private static boolean isPortInUse(int port) {
        try (Socket socket = new Socket("localhost", port)) {
            return true;
        } catch (ConnectException e) {
            return false;
        } catch (IOException e) {
            logger.debug("检查端口{}占用情况时发生异常: ", port, e);
            return false;
        }
    }
    
    /**
     * 杀死占用指定端口的进程
     *
     * @param port 被占用的端口号
     */
    private static void killProcessUsingPort(int port) {
        try {
            String os = System.getProperty("os.name").toLowerCase();
            Process process;
            
            if (os.contains("win")) {
                // Windows系统：使用PowerShell命令终止占用端口的进程
                String[] command = {
                    "powershell",
                    "-Command",
                    "Get-NetTCPConnection -LocalPort " + port + " | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force }"
                };
                process = Runtime.getRuntime().exec(command);
            } else {
                // Unix/Linux/Mac系统：使用lsof和kill命令
                process = Runtime.getRuntime().exec("lsof -t -i:" + port + " | xargs kill -9");
            }
            
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                logger.info("成功终止占用端口 {} 的进程", port);
            } else {
                logger.warn("终止占用端口 {} 的进程可能失败，退出代码: {}", port, exitCode);
            }
        } catch (Exception e) {
            logger.error("终止占用端口 {} 的进程时发生异常: ", port, e);
        }
    }
}